"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.trigger = exports.track = exports.createReactiveEffect = exports.effect = exports.createDepsMap = exports.isEffect = exports.ITERATE_KEY = void 0;
var utils_1 = require("../utils");
var effectStack = []; // 适应多层effect
var activeEffect; // 当前存储的effect方法
exports.ITERATE_KEY = Symbol('');
function isEffect(fn) {
    return fn && fn._isEffect === true;
}
exports.isEffect = isEffect;
/**
 * 创建Deps依赖
 * @return {DepsMap} Deps依赖
 */
exports.createDepsMap = function () { return new Map(); };
/**
 * 创建effect
 * @param fn {Function} 要观察的方法
 * @param iterate {Boolean} 是否监听根
 * @return {ReactiveEffect} 返回effect
 */
function effect(fn, iterate) {
    if (iterate === void 0) { iterate = false; }
    if (isEffect(fn)) {
        fn = fn.raw;
    }
    var effect = createReactiveEffect(fn, iterate);
    effect();
    return effect;
}
exports.effect = effect;
/**
 * 创建effect
 * @param fn {Function} 要观察的方法
 * @param iterate {Boolean} 是否监听根
 * @return {ReactiveEffect} 返回effect
 */
function createReactiveEffect(fn, iterate) {
    if (iterate === void 0) { iterate = false; }
    var effect = function reactiveEffect() {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        try {
            effectStack.push(effect);
            activeEffect = effect;
            return fn.apply(void 0, args);
        }
        finally {
            effectStack.pop();
            activeEffect = effectStack[effectStack.length - 1];
        }
    };
    effect.raw = fn;
    effect._isEffect = true;
    effect.iterate = iterate;
    effect.deps = [];
    effect.stop = function () { effect.deps.forEach(function (dep) { return dep.delete(effect); }); };
    return effect;
}
exports.createReactiveEffect = createReactiveEffect;
/**
 * 值获取，获取effect存入Deps中
 * @param depsMap {Map} Deps依赖
 * @param key {unknow} 键值
 */
function track(depsMap, key) {
    // effect不存在，不track
    if (activeEffect === undefined)
        return;
    // 如果是iterate，存入ITERATE_KEY
    activeEffect.iterate && addDeps(depsMap, exports.ITERATE_KEY, activeEffect);
    addDeps(depsMap, key, activeEffect);
}
exports.track = track;
/**
 * 值改变，执行Deps中对应键值的函数
 * @param depsMap {Map} Deps依赖
 * @param key {unknow} 键值
 * @param add {Boolean} 是否是新增属性
 */
function trigger(depsMap, key, isAdd) {
    if (isAdd === void 0) { isAdd = false; }
    // 添加时，将ITERATE_KEY中的deps复制进新属性中
    isAdd && addDeps(depsMap, key, depsMap.get(exports.ITERATE_KEY));
    // 执行
    var deps = depsMap.get(key);
    deps && deps.forEach(function (fn) { return fn.raw(); });
}
exports.trigger = trigger;
/**
 * 添加dep依赖
 * @param depsMap {Map} Deps依赖
 * @param key {unknow} 键值
 * @param effects {ReactiveEffect<any> | Set<ReactiveEffect<any>>} 要添加的effect
 */
function addDeps(depsMap, key, effects) {
    var deps = depsMap.get(key);
    !deps && depsMap.set(key, deps = new Set());
    // deps中添加effect
    if (utils_1.isFunction(effects)) {
        effects.deps.push(deps);
        !deps.has(effects) && deps.add(effects);
    }
    else {
        effects && effects.forEach(function (effect) {
            effect.deps.push(deps);
            !deps.has(effect) && deps.add(effect);
        });
    }
}
